分享人:邱天成
1.背景介绍
2.知识剖析
3.常见问题
4.解决方案
5.编码实战
6.扩展思考
7.参考文献
8.更多讨论
this是JavaScript语言中定义的众多关键字之一,它的特殊在于它自动定义于每一个函数域内,在函数运行时,this会自动生成一个内部对象,这个对象只能在函数内部使用。同时,随着函数使用场合的不同,this的值会发生变化。但是有一个总的原则,那就是this指的是,调用函数的那个对象。
在JavaScript中,this是动态绑定的,它可以是全局对象、当前对象或者任意对象,这完全取决于函数的调用方式。这就导致了this具备了多重含义,可以使得JavaScript更灵活的使用。但是,带来了灵活性的同时也会给我们初学者带来不少困惑。
关于全局环境中this的指向
var name = '小明';
function look() {
var name = '二明';
console.log(this.name);
console.log(this);
};
look(); //小明
//window.look();
总结:在全局作用域中它的 this 执行当前的全局对象(浏览器端是 Window),所以才会在全局环境下查找'name',然后打印出来
关于全局环境中this的指向
var name = '小明';
var name2 = {
name: '二明',
age: 20,
look: function(){
console.log(this.name);
console.log(this.age);
}
}
name2.look(); //二明;20
//window.name2.look();
这里的打印的结果是打印的第一个是二明,第二个是20。因为调用look函数的是name2这个对象,所以this指向的是name2中的name属性
this的指向只在函数中定义的话是确定不了的,只有当被函数执行的时候才能确定this到底指向谁,也就是谁调用了这个函数。
var name = '小明';
var name2 = {
name: '二明',
func:{
name: '三明',
look: function(){
console.log(this.name);
}
}
}
name2.func.look();
window.name2.func.look();
这里的话,第一个是函数被name2调用的,本应打印的是二明,但是最后的打印结果却是三明,是为什么呢。
1.如果一个函数有this,但是它没有被上一级对象所调用,那么它指向的就是window。在严格模式下指向的是undefined。
2.如果一个函数中有this,这个函数有被上一级所调用,那么它指向的就是调用它的对象。
3.如果一个函数中有this,且这个函数外层被多个对象包含,尽管最终这个函数是被最外层的对象所调用,this指向的也只是函数上一级的对象。
var name = '小明';
var name2 = {
name: '二明',
func:{
look: function(){
console.log(this.name);
}
}
}
name2.func.look();
window.name2.func.look();
虽然函数look()最终是被func调用,哪怕func中没有name这个属性,this指向的依然是func,所以打印的结果为undefined。
var name = '小明';
var name2 = {
name: '二明',
func:{
name: '三明',
look: function(){
console.log(this.name);
}
}
}
var a = name2.func.look;
a();
这里的话this最终打印的是小明,却不是我们想象中的三明,这是因为我们重新声明变量a,并把look函数赋值给它,最后执行函数a()的时候,调用a()是Window对象。
还是那句话:谁调用this,this就指向谁$(this)是jquery对象,能调用jquery的方法,例如click(), keyup()。 而this,则是html元素对象,能调用元素属性,例如this.id,this.value。 例如假设已经使得this和$(this)都指向了input对象了,若要获得input的值,可以this.value,但$(this)就得$(this).val()。
var obj = {
name: 'qiutc',
foo: function() {
console.log(this);
},
foo2: function() {
console.log(this);
setTimeout(this.foo, 1000);
}
}
obj.foo2();
现象:两次打印的this不一样
可以这么这么解决:利用 闭包 的特性来处理
var obj = {
name: 'qiutc',
foo: function() {
console.log(this);
},
foo2: function() {
console.log(this);
var _this = this;
setTimeout(function() {
console.log(this); // Window
console.log(_this); // Object {name: "qiutc"}
}, 1000);
}
}
obj.foo2();
可以看到直接用 this 仍然是 Window;因为 foo2 中的 this 是指向 obj,我们可以先用一个变量 _this 来储存,然后在回调函数中使用 _this,就可以指向当前的这个对象了
执行这段代码我们会发现两次打印出来的 this 是不一样的:
第一次是 foo2 中直接打印 this,这里指向 obj 这个对象,我们毋庸置疑;
但是在 setTimeout 中执行的 this.foo ,却指向了全局对象,这里不是把它当作函数的方法使用吗?这一点经常让很多初学者疑惑;
其实,setTimeout 也只是一个函数而已,函数必然有可能需要参数,我们把 this.foo 当作一个参数传给 setTimeout 这个函数,就像它需要一个 fun 参数,在传入参数的时候,其实做了个这样的操作
fun = this.foo,看到没有,这里我们直接把 fun 指向 this.foo 的引用;执行的时候其实是执行了 fun() 所以已经和 obj 无关了,它是被当作普通函数直接调用的,因此 this 指向全局对象。
这个问题是很多异步回调函数中普遍会碰到的;
问题:当this遇到return时会发生什么?
如果返回值是一个对象,那么this指向的就是那个返回的对象,如果返回值不是一个对象那么this还是指向函数的实例。
参考一: 彻底理解JS中this的指向
参考二: 阮一峰的博客
感谢大家观看
BY: 邱天成
参考ppt: 孙剑立、刘洪利